import requests
from fake_useragent import UserAgent
import time
import json
import pandas as pd
from pyecharts.charts import Bar
from pyecharts import options as opts
import warnings
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
warnings.filterwarnings("ignore")


ua = UserAgent()


def get_weekly_data(number):
    headers = {'User-Agent': ua.random}
    url = f'https://api.bilibili.com/x/web-interface/popular/series/one?number={number}'
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        return response.json()
    else:
        time.sleep(5)  # 等待5秒后重试
        return get_weekly_data(number)


def main():
    for number in range(277, 278):  # 我们要爬取某期的数据，可以更改
        data = get_weekly_data(number)
        with open(f'datas/weekly_data_{number}.json', 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False)
        time.sleep(1)  # 避免请求过于频繁


if __name__ == '__main__':
    main()


def clean_data(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        my_df = json.load(f)
    # print(my_df)
    # 选择有价值字段
    videos = my_df['data']['list']
    print(videos[0])
    all_df = pd.DataFrame()
    a=1
    # 清洗出所需的数据
    for em in videos:
        a=a+1
        df = pd.DataFrame(em['stat'], columns=['aid', 'view', 'danmaku', 'reply',
                                       'favorite', 'coin', 'share', 'now_rank',
                                       'his_rank', 'like', 'dislike', 'vt', 'vv1'],
                          index=[a])
        df['up_name']=em['owner']['name']
        df['title_name']=em['title']
        all_df = pd.concat([all_df, df], ignore_index=True)


    return all_df


# 合并所有清洗后的数据
all_data = pd.DataFrame()
for number in range(277, 278):
    file_path = f'datas/weekly_data_{number}.json'
    df = clean_data(file_path)
    df.set_index(['aid'], inplace=True)
    print(df)
    all_data = pd.concat([all_data, df], ignore_index=True)
all_data.to_csv('data.csv')
# print(all_data)
# 分析各收录视频的基本播放情况



# 以播放量数据可视化为例
bar = Bar()
# bar.add_xaxis(list(play_stats.index))
# bar.add_yaxis("播放量", list(play_stats.values))
bar.set_global_opts(title_opts=opts.TitleOpts(title="播放量数据可视化"))
bar.render('play_stats.html')


# 读取CSV文件
df = pd.read_csv('data.csv')


# 定义一个函数来将标题按每6个字符换行
def wrap_title(title, char_limit=6):
    words = []
    words = [title[i:i + char_limit] for i in range(0, len(title), char_limit)]
    return '\n'.join(words)


plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]  # 设置中文显示字体

# 按照danmaku列的值从大到小排序
sorted_df = df.sort_values(by='danmaku', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['wrapped_title'], top_10['danmaku'], color='#27DEB4')
plt.title('弹幕数最多的视频前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('弹幕数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
# 由于换行后标题可能占用更多空间，需要调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
plt.savefig('弹幕数最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按'favorite'列的值从大到小排序
sorted_df = df.sort_values(by='favorite', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['favorite'], color='#D64912')

# 设置图表标题和坐标轴标签
plt.title('收藏数前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('收藏数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('收藏数最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()


# 按'reply'列的值从大到小排序
# df_sorted = df[df['reply'].notna()].sort_values(by='reply', ascending=False)
sorted_df = df.sort_values(by='reply', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['reply'], color='#DE84F0')

# 设置图表标题和坐标轴标签
plt.title('评论数前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('评论数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('评论数最多的视频前十名', dpi=800, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()


# 按'coin'列的值从大到小排序
sorted_df = df.sort_values(by='coin', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['coin'], color='#F09495')

# 设置图表标题和坐标轴标签
plt.title('投币数前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('投币数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('投币数最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()


# 按'view'列的值从大到小排序
sorted_df = df.sort_values(by='view', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['view'], color='#59C4A1')

# 设置图表标题和坐标轴标签
plt.title('播放量前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('播放量', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('播放量最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()


# 按'share'列的值从大到小排序
sorted_df = df.sort_values(by='share', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['share'], color='#4ECCCC')

# 设置图表标题和坐标轴标签
plt.title('分享前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('分享次数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('分享最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()



# 按'like'列的值从大到小排序
sorted_df = df.sort_values(by='like', ascending=False)
# 选择前10个视频
top_10 = sorted_df.head(10)
top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 设置图表大小
plt.figure(figsize=(20, 12), facecolor='#EFECDD')

# 绘制柱状图
plt.bar(top_10['wrapped_title'], top_10['like'], color='#4A61CC', )
# 设置图表标题和坐标轴标签
plt.title('点赞前十名视频的柱状图', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('点赞次数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')
plt.gca().set_xticklabels(top_10['wrapped_title'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.savefig('点赞最多的视频前十名', dpi=800, transparent=False, bbox_inches='tight')
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色

# 显示图表
plt.tight_layout()  # 自动调整子图参数, 使之填充整个图像区域
plt.show()


###########################################################


# 按照danmaku列的值从大到小排序
sorted_df = df.sort_values(by='danmaku', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['danmaku'], color='#27DEB4')
plt.title('弹幕数最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('弹幕数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 由于换行后标题可能占用更多空间，需要调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('弹幕数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照favorite列的值从大到小排序
sorted_df = df.sort_values(by='favorite', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['favorite'], color='#D64912')
plt.title('收藏数最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('收藏数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('收藏数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照reply列的值从大到小排序
sorted_df = df.sort_values(by='reply', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['reply'], color='#DE84F0')
plt.title('评论数最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('收藏数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('评论数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照coin列的值从大到小排序
sorted_df = df.sort_values(by='coin', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['coin'], color='#F09495')
plt.title('视频投币数最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('视频投币数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('视频投币数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照view列的值从大到小排序
sorted_df = df.sort_values(by='view', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['view'], color='#59C4A1')
plt.title('视频播放量最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('视频播放量', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('视频播放量最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照share列的值从大到小排序
sorted_df = df.sort_values(by='share', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['share'], color='#4ECCCC')
plt.title('视频分享最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('视频分享数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 需要调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('视频分享数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()


# 按照like列的值从大到小排序
sorted_df = df.sort_values(by='like', ascending=False)
# 取出弹幕数前十名的视频
top_10 = sorted_df.head(10)
# top_10['wrapped_title'] = top_10['title_name'].apply(wrap_title)
# 绘制柱状图
plt.figure(figsize=(20, 12), facecolor='#EFECDD')  # 调整图表大小以适应换行后的标题
plt.bar(top_10['up_name'], top_10['like'], color='#4A61CC')
plt.title('视频点赞数最多的up主前十名', fontsize=30, fontweight='bold', fontname='Microsoft YaHei')
plt.ylabel('视频点赞数', fontsize=20, fontweight='bold', fontname='Microsoft YaHei')

# 需要调整x轴的tick_params来避免标签与柱状图重叠
plt.gca().set_xticklabels(top_10['up_name'], rotation=0, ha="center", fontsize=15, fontweight='bold')
plt.gca().tick_params(axis='x', which='major', pad=15)  # 增加x轴标签与轴线的距离
ax = plt.gca()  # 获取当前坐标轴
ax.set_facecolor('#EFECDD')  # 设置坐标轴的背景颜色
plt.savefig('视频点赞数最多的up主前十名', dpi=800, transparent=False, bbox_inches='tight')
# 显示图表
plt.tight_layout()  # 尝试自动调整布局
plt.show()